//
// Created by zhengjuping on 24-9-11.
//

#include <utility>
#include <stdexcept>
#include <cstring>
#include <esp_log.h>

#include "include/AdvertisementData.h"

#define TAG "AdvertisementData"

AdvertisementData::AdvertisementData(std::string name, const BleUuid &serviceUuid):
        _name(std::move(name)),
        _serviceUuid(serviceUuid),
        _advData(){

    //flags
    _advData.push_back(0x02);
    _advData.push_back(0x01);
    _advData.push_back(0x06);

    //txPower
    _advData.push_back(0x02);
    _advData.push_back(0x0a);
    _advData.push_back(0xeb);

    //service UUID
    BleUuid::Width width = _serviceUuid.getWidth();
    switch (width) {
        case BleUuid::Width::UUID_16:
            _advData.push_back(0x03);
            _advData.push_back(0x03);
            _advData.push_back(_serviceUuid.getUuid16() & 0xff);
            _advData.push_back(_serviceUuid.getUuid16() >> 8);
            break;
        case BleUuid::Width::UUID_32:
            _advData.push_back(0x05);
            _advData.push_back(0x05);
            _advData.push_back(_serviceUuid.getUuid32() >> 24);
            _advData.push_back(_serviceUuid.getUuid32() >> 16);
            _advData.push_back(_serviceUuid.getUuid32() >> 8);
            _advData.push_back(_serviceUuid.getUuid32() & 0xff);
            break;

        default:
            _advData.push_back(0x03);
            _advData.push_back(0x03);
            _advData.push_back(0xFF);
            _advData.push_back(0x00);
    }

    int32_t deviceName = _name.length();
    _advData.push_back(deviceName + 1);
    _advData.push_back(0x09);
    for (int i = 0; i < deviceName; ++i) {
        _advData.push_back(_name[i]);
    }

    if( _advData.size() > 31 ){
        throw std::runtime_error("adv data too long");
    }
}

int32_t AdvertisementData::toData(uint8_t *data, uint16_t inDataLength, uint32_t &outDatalength) {
    if( inDataLength < _advData.size() ){
        throw std::runtime_error("data buffer too small");
    }
    memcpy(data, _advData.data(), _advData.size());
    outDatalength = _advData.size();
    return 0;
}

void AdvertisementData::dump() {
    ESP_LOGE(TAG, "AdvertisementData dump");
    esp_log_buffer_hex_internal(TAG, _advData.data(), _advData.size(), ESP_LOG_WARN);
}
